home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / winsock / ircii2-6.zip / SRC\IRCII-2.6\SOURCE\IRCSERV.C < prev    next >
C/C++ Source or Header  |  1994-12-28  |  6KB  |  318 lines

  1. /*
  2.  * ircserv.c: A quaint little program to make irc life PING free 
  3.  *
  4.  * Written By Michael Sandrof
  5.  *
  6.  * Copyright(c) 1990 
  7.  *
  8.  * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
  9.  */
  10.  
  11. #ifndef lint
  12. static    char    rcsid[] = "@(#)$Id: ircserv.c,v 1.17 1994/07/25 13:36:10 mrg Stab $";
  13. #endif
  14.  
  15. #include <stdio.h>
  16. #include <sys/types.h>
  17. #include <sys/socket.h>
  18. #include <sys/file.h>
  19. #include <netinet/in.h>
  20. #include <netdb.h>
  21. #include <arpa/inet.h>
  22. #include <errno.h>
  23. #include <signal.h>
  24.  
  25. #include "defs.h"
  26. #include "irc_std.h"
  27.  
  28. /* machines we don't want to use <unistd.h> on 'cause its broken */
  29. #if defined(pyr) || defined(_SEQUENT_)
  30. # undef HAVE_UNISTD_H
  31. #endif
  32.  
  33. #ifdef HAVE_UNISTD_H
  34. # include <unistd.h>
  35. #endif
  36.  
  37. #ifdef HAVE_SYS_UN_H
  38. #include <sys/un.h>
  39. int    connect_to_unix();
  40. #endif /* HAVE_SYS_UN_H */
  41.  
  42. #undef NON_BLOCKING
  43.  
  44. extern    void    set_socket_options __P((int));
  45. extern    int    new_select();
  46. extern    int    dgets();
  47.  
  48. char    *new_malloc(size)
  49. int    size;
  50. {
  51.     char    *ptr;
  52.  
  53.     if ((ptr = (char *) malloc(size)) == (char *) 0)
  54.     {
  55.         printf("-1 0\n");
  56.         exit(1);
  57.     }
  58.     return (ptr);
  59. }
  60.  
  61. /*
  62.  * new_free:  Why do this?  Why not?  Saves me a bit of trouble here and
  63.  * there 
  64.  */
  65. void    new_free(ptr)
  66. char    **ptr;
  67. {
  68.     if (*ptr)
  69.     {
  70.         free(*ptr);
  71.         *ptr = (char *) 0;
  72.     }
  73. }
  74.  
  75. /*
  76.  * Connect_By_Number Performs a connecting to socket 'service' on host
  77.  * 'host'.  Host can be a hostname or ip-address.  If 'host' is null, the
  78.  * local host is assumed.   The parameter full_hostname will, on return,
  79.  * contain the expanded hostname (if possible).  Note that full_hostname is a
  80.  * pointer to a char *, and is allocated by connect_by_numbers() 
  81.  *
  82.  * Errors: 
  83.  *
  84.  * -1 get service failed 
  85.  *
  86.  * -2 get host failed 
  87.  *
  88.  * -3 socket call failed 
  89.  *
  90.  * -4 connect call failed 
  91.  */
  92. int    connect_by_number(service, host)
  93. int    service;
  94. char    *host;
  95. {
  96.     int    s;
  97.     char    buf[100];
  98.     struct    sockaddr_in    server;
  99.     struct    hostent    *hp;
  100.  
  101.     if (host == (char *) 0)
  102.     {
  103.         gethostname(buf, sizeof(buf));
  104.         host = buf;
  105.     }
  106.     if ((server.sin_addr.s_addr = inet_addr(host)) == -1)
  107.     {
  108.         if ((hp = gethostbyname(host)) != NULL)
  109.         {
  110.             bzero((char *) &server, sizeof(server));
  111.             bcopy(hp->h_addr, (char *) &server.sin_addr,
  112.                 hp->h_length);
  113.             server.sin_family = hp->h_addrtype;
  114.         }
  115.         else
  116.             return (-2);
  117.     }
  118.     else
  119.         server.sin_family = AF_INET;
  120.     server.sin_port = (unsigned short) htons(service);
  121.     if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  122.         return (-3);
  123.     set_socket_options(s);
  124. #ifdef PRIV_PORT
  125.     if (geteuid() == 0)
  126.     {
  127.         struct    sockaddr_in    localaddr;
  128.         int    portnum;
  129.  
  130.         localaddr = server;
  131.         localaddr.sin_addr.s_addr = INADDR_ANY;
  132.         for (portnum = 1023; portnum > PRIV_PORT; portnum--)
  133.         {
  134.             localaddr.sin_port = htons(portnum);
  135.             if (bind(s, (struct sockaddr *) &localaddr,
  136.                     sizeof(localaddr)) != -1)
  137.                 break;
  138.         }
  139.     }
  140. #endif /*PRIV_PORT*/
  141.     if (connect(s, (struct sockaddr *) &server, sizeof(server)) < 0)
  142.     {
  143.         close(s);
  144.         return (-4);
  145.     }
  146.     return (s);
  147. }
  148.  
  149. /*
  150.  * ircserv: This little program connects to the server (given as arg 1) on
  151.  * the given port (given as arg 2).  It then accepts input from stdin and
  152.  * sends it to that server. Likewise, it reads stuff sent from the server and
  153.  * sends it to stdout.  Simple?  Yes, it is.  But wait!  There's more!  It
  154.  * also intercepts server PINGs and automatically responds to them.   This
  155.  * frees up the process that starts ircserv (such as IRCII) to pause without
  156.  * fear of being pooted off the net. 
  157.  *
  158.  * Future enhancements: No-blocking io.  It will either discard or dynamically
  159.  * buffer anything that would block. 
  160.  */
  161. void    main(argc, argv)
  162. int    argc;
  163. char    **argv;
  164. {
  165.     int    des;
  166.     fd_set    rd;
  167.     int    done = 0,
  168.         c;
  169.     char    *ptr,
  170.         buffer[BUFSIZ + 1],
  171.         pong[BUFSIZ + 1];
  172. #ifdef NON_BLOCKING
  173.     char    block_buffer[BUFSIZ + 1];
  174.     fd_set    *wd_ptr = (fd_set *) 0,
  175.         wd;
  176.     int    wrote;
  177. #endif /* NON_BLOCKING */
  178.  
  179.     if (argc < 3)
  180.         exit(1);
  181. #ifdef HAVE_SYS_UN_H
  182.     if (*argv[1] == '/')
  183.         des = connect_to_unix(argv[1]);
  184.     else
  185. #endif /* HAVE_SYS_UN_H */
  186.         des = connect_by_number(atoi(argv[2]), argv[1]);
  187.     if (des < 0)
  188.         exit(des);
  189.     fflush(stdout);
  190.  
  191.     (void) MY_SIGNAL(SIGTERM, SIG_IGN, 0);
  192.     (void) MY_SIGNAL(SIGSEGV, SIG_IGN, 0);
  193.     (void) MY_SIGNAL(SIGPIPE, SIG_IGN, 0);
  194. #ifdef SIGWINCH
  195.     (void) MY_SIGNAL(SIGWINCH, SIG_IGN, 0);
  196. #endif
  197. #ifdef SIGBUS
  198.     (void) MY_SIGNAL(SIGBUS, SIG_IGN, 0);
  199. #endif
  200. #ifdef NON_BLOCKING
  201.     if (fcntl(1, F_SETFL, FNDELAY))
  202.         exit(1);
  203. #endif /* NON_BLOCKING */
  204.     while (!done)
  205.     {
  206.         fflush(stderr);
  207.         FD_ZERO(&rd);
  208.         FD_SET(0, &rd);
  209.         FD_SET(des, &rd);
  210. #ifdef NON_BLOCKING
  211.         if (wd_ptr)
  212.         {
  213.             FD_ZERO(wd_ptr);
  214.             FD_SET(1, wd_ptr);
  215.         }
  216.         switch (new_select(&rd, wd_ptr, NULL))
  217.         {
  218. #else
  219.         switch (new_select(&rd, (fd_set *) 0, NULL))
  220.         {
  221. #endif /* NON_BLOCKING */
  222.         case -1:
  223.         case 0:
  224.             break;
  225.         default:
  226. #ifdef NON_BLOCKING
  227.             if (wd_ptr)
  228.             {
  229.                 if (FD_ISSET(1, wd_ptr))
  230.                 {
  231.                     c = strlen(block_buffer);
  232.                     if ((wrote = write(1, block_buffer,
  233.                             c)) == -1)
  234.                     {
  235.                         wd_ptr = &wd;
  236.                     }
  237.                     else if (wrote < c)
  238.                     {
  239.                         strcpy(block_buffer,
  240.                             &(block_buffer[wrote]));
  241.                         wd_ptr = &wd;
  242.                     }
  243.                     else
  244.                         wd_ptr = (fd_set *) 0;
  245.                 }
  246.             }
  247. #endif /* NON_BLOCKING */
  248.         if (FD_ISSET(0, &rd))
  249.             {
  250.                 if (0 != (c = dgets(buffer, BUFSIZ, 0,
  251.                             (char *) 0)))
  252.                     write(des, buffer, c);
  253.                 else
  254.                     done = 1;
  255.             }
  256.             if (FD_ISSET(des, &rd))
  257.             {
  258.                 if (0 != (c = dgets(buffer, BUFSIZ, des,
  259.                             (char *) 0)))
  260.                 {
  261.                     if (strncmp(buffer, "PING ", 5) == 0)
  262.                     {
  263.                         if ((ptr = (char *) 
  264.                             index(buffer, ' ')) != NULL)
  265.                         {
  266.                             sprintf(pong, "PONG user@host %s\n", ptr + 1);
  267.                             write(des, pong, strlen(pong));
  268.                         }
  269.                     }
  270.                     else
  271.                     {
  272. #ifdef NON_BLOCKING
  273.                         if ((wrote = write(1, buffer,
  274.                                 c)) == -1)
  275.                             wd_ptr = &wd;
  276.                         else if (wrote < c)
  277.                         {
  278.                             strcpy(block_buffer,
  279.                                 &(buffer[wrote]));
  280.                             wd_ptr = &wd;
  281.                         }
  282. #else
  283.                         write(1, buffer, c);
  284. #endif /* NON_BLOCKING */
  285.                     }
  286.                 }
  287.                 else
  288.                     done = 1;
  289.             }
  290.         }
  291.     }
  292. }
  293.  
  294.  
  295. #ifdef HAVE_SYS_UN_H
  296. /*
  297.  * Connect to a UNIX domain socket. Only works for servers.
  298.  * submitted by Avalon for use with server 2.7.2 and beyond.
  299.  */
  300. int    connect_to_unix(path)
  301. char    *path;
  302. {
  303.     struct    sockaddr_un    un;
  304.     int    sock;
  305.  
  306.     sock = socket(AF_UNIX, SOCK_STREAM, 0);
  307.  
  308.     un.sun_family = AF_UNIX;
  309.     strcpy(un.sun_path, path);
  310.     if (connect(sock, (struct sockaddr *)&un, strlen(path)+2) == -1)
  311.     {
  312.         close(sock);
  313.         return -1;
  314.     }
  315.     return sock;
  316. }
  317. #endif /* HAVE_SYS_UN_H */
  318.